home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / uip / msg / msg1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-11  |  18.1 KB  |  865 lines

  1. /*
  2.  *            M S G 1 . C
  3.  *
  4.  * Functions -
  5.  *    main        main command loop
  6.  *
  7.  *
  8.  *  This has wended its way from Illinois through many other sites.
  9.  *  It approximates the Tenex MSG program, written by John Vittal.
  10.  *
  11.  *  Oct 80  Stu Cracraft    Moby edit for conversion from V6 to V7
  12.  *
  13.  *  Nov 80  Dave Crocker    Retrofit for V6 compatibility; add stdio
  14.  *  -May 81            cleanup & improve error detect/correct
  15.  *
  16.  *  Jun 81  Dave Crocker    gitr() fixed '?' case
  17.  *                overwrit() confirm file deletion and
  18.  *                have temp file in same directory as original
  19.  *                xeq() call to date needed 0 at end of args
  20.  *                 change 'index' to 'equal' for reply tests
  21.  *
  22.  *  Jul 81  Dave Crocker    stop mapping DEL->newline in ttychar()
  23.  *                fix settype(t) to make txtmtch work
  24.  *                 add 'new' messages added after folder open
  25.  *
  26.  *  Jul 81  Doug Kingston    getnum() check for < 0 -> 0.
  27.  *  Sep 81  Dave Crocker    prmsg() catch form-feeds
  28.  *  Jan 82  Doug Kingston    Modified for use on BRL machines
  29.  *                Threw out some deadwood.
  30.  *  Mar 82  Doug Kingston    Fixed blank line bug in setup().
  31.  *  Jun 82  Doug Kingston    Fixed the "type current" bug.
  32.  *
  33.  *    06/07/82  MJM        First pass on cleanup prior to changover
  34.  *                to dual file version.
  35.  *
  36.  *    06/08/82  MJM    Split the enormous MSG program into pieces.
  37.  *            Added new help messages.
  38.  *
  39.  *    06/10/82  MJM    Optimized file reading, header parsing, eliminated
  40.  *            re-read after overwrite, added additional flags
  41.  *            processing, 'k', '$', ',' commands, plus general
  42.  *            cleanup and optimization.
  43.  *
  44.  *    07/12/81  MJM    Fixed up bugs in Quit signal processing, and in the
  45.  *            ',' command.
  46.  *
  47.  *    09/10/82  MJM    Converted output to use STDIO also.
  48.  *
  49.  *    09/13/82  MJM    Added Undigestify code.  Switched msg[] to msgp[].
  50.  *
  51.  *    11/22/82  HW    Added Keyword stripping and Xtra options.
  52.  *
  53.  *    12/04/82  HW    Added P flag, dot options.
  54.  *
  55.  *    03/16/83  MJM    VAXorcised the code.
  56.  *
  57.  *    03/29/83  MJM    Made eXtend a command, not a mode.  Added "d" debug.
  58.  *
  59.  *    08/11/83  DPK    Fixed interrupt handling, added "." in number ranges,
  60.  *            fixed continuation line handling, added close of files
  61.  *            prior to execs, added wait loop.
  62.  *
  63.  *      11/01/85       Craig Partridge: fix bugs in using spool directory
  64.  *
  65.  *    04/20/88  ECB    Added "twowinfil" option.
  66.  */
  67.  
  68. extern char *verdate;
  69.  
  70. #include "util.h"
  71. #include "mmdf.h"
  72. #include <pwd.h>
  73. #include <signal.h>
  74. #include <sys/stat.h>
  75. #include <sgtty.h>
  76. #ifdef V4_2BSD
  77. #include <sys/ioctl.h>
  78. #endif V4_2BSD
  79. #include "./msg.h"
  80.  
  81. extern    int Nmsgs;
  82.  
  83. char    lastc = '\n';
  84. char    ascending = TRUE;
  85.  
  86. extern    sigtype    (*old3)();
  87. extern    sigtype    (*old13)();
  88. extern    sigtype    (*old18)();
  89.  
  90. extern    int    pagesize;
  91. extern    int    linelength;
  92.  
  93. extern    int    paging;
  94. extern    int    keystrip;
  95. extern    int    bdots;
  96. extern    int    mdots;
  97. extern    int    bprint;
  98. extern    int    quicknflag;
  99. extern    int    prettylist;
  100. extern    int    filoutflag;
  101. extern    int    binsavflag;
  102. extern    char    *resendprog;
  103. extern    char    *savmsgfn;
  104. extern    char    *dflshell;
  105. extern    char    *dfleditor;
  106. extern    char    *verdate;
  107.  
  108. int    outmem = FALSE;
  109. int    readonly = FALSE;
  110. char    *msgrcfn = ".msgrc";
  111. char    *binarypre = "._";    /* Prefix for binary map filename */
  112.  
  113. FILE * filefp = NULL;        /* Input FILEp */
  114. FILE * outfp = NULL;        /* Output FILEp */
  115. FILE * binfp = NULL;        /* Binary FILEp */
  116.  
  117. /*
  118.  * Place to put temporary message file, while doing
  119.  * the overwrite in current directory
  120.  */
  121. char    *tempname = "msgtmp.XXXXXX";
  122.  
  123. /* The HELP command lists are defined in msg3.c */
  124. extern char    *cmdlst[];
  125. extern char    *xtcmdlst[];
  126. extern char    *ctime();
  127.  
  128. /*
  129.  *            M A I N
  130.  */
  131. main( argc, argv)
  132. int     argc;
  133. char   *argv[];
  134. {
  135.     int     restrt;
  136.     int    j;
  137.     char    tb[1024];
  138.     register struct message **mp;
  139.     extern struct passwd *getpwuid();
  140.     extern int onhangup();
  141.     struct passwd  *pwdptr;
  142.     char *uterm;
  143.     int realid;
  144.     int effecid;
  145.     char *tmpname;
  146.     extern char *getlogin();
  147.     extern char *getenv();
  148. #ifdef TIOCGWINSZ
  149.     struct winsize ws;
  150. #endif
  151.  
  152.     setbuf( stdout, ttyobuf);
  153.     signal( SIGHUP, onhangup );
  154.     orig = signal( SIGINT, SIG_DFL);
  155.     old3 = signal( SIGQUIT, SIG_IGN);
  156.     old13 = signal( SIGPIPE, onnopipe);
  157. #ifdef SIGTSTP
  158.     if( (old18 = signal(SIGTSTP,SIG_IGN)) == SIG_DFL )
  159.         signal(SIGTSTP,onstop);
  160. #endif SIGTSTP
  161.  
  162.     printf( "MSG (%s)  Type ? for help.\r\n", verdate);
  163.     fflush( stdout);
  164.  
  165.     mmdf_init("msg");        /* Should be mmdf_init() ??? */
  166.  
  167.     homedir = getenv("HOME");
  168.     tmpname = getlogin();
  169.  
  170.     if ((tmpname == 0) || (homedir == 0))
  171.     {
  172.         getwho( &realid, &effecid);
  173.  
  174.         /* get passwd entry */
  175.         if ((pwdptr = getpwuid(realid)) == 0)
  176.         {
  177.         if (tmpname == 0)
  178.             tmpname = "UnknownUsername";
  179.  
  180.         if (homedir == 0)
  181.             homedir = "";
  182.         }
  183.         else
  184.         {
  185.         if (tmpname == 0)
  186.             tmpname = pwdptr->pw_name;
  187.  
  188.         if (homedir == 0)
  189.             homedir = pwdptr->pw_dir;
  190.         }
  191.     }
  192.  
  193.     strcpy(username,tmpname);
  194.  
  195.     sprintf( maininbox, "%s/%s",
  196.         (mldfldir==0 || isnull(mldfldir[0])) ? homedir : mldfldir,
  197.         (mldflfil==0 || isnull(mldflfil[0])) ? username : mldflfil);
  198.  
  199.     /* Build default mailbox name */
  200.     strcpy( filename, maininbox);
  201.  
  202.     sprintf( defmbox, "%s/%s", homedir, savmsgfn);
  203.     strcpy( defoutfile, defmbox);
  204.  
  205.     strcpy( draftorig, "draft_original" );
  206.     /* Build strings for 2-window mode */
  207.     sprintf( draft_work, "%s/draft_work", homedir );
  208.     sprintf( draft_original, "%s/%s", homedir, draftorig );
  209.  
  210.     /* Get environment variables */
  211.     if( (ushell = getenv("SHELL")) == NULL )
  212.         ushell = dflshell;
  213.     if( (ueditor = getenv("EDITOR")) == NULL )
  214.         ueditor = dfleditor;
  215.  
  216.     /* The default 2-window filter is just the editor */
  217.     strcpy( twowinfil, ueditor);
  218.  
  219. #ifdef TIOCGWINSZ
  220.     if (ioctl(fileno(stdout), TIOCGWINSZ, &ws) != -1) {
  221.         if (ws.ws_row > 0) pagesize = (int)ws.ws_row;
  222.         if (ws.ws_col > 0) linelength = (int)ws.ws_col;
  223.     } else
  224. #endif TIOCGWINSZ    
  225.     if( (uterm = getenv("TERM")) != NULL && tgetent(tb,uterm) == 1) {
  226.         if ((j = tgetnum("li")) > 0)
  227.             pagesize = j;
  228.         if ((j = tgetnum("co")) > 0)
  229.             linelength = j;
  230.     }
  231.  
  232.     /* Check for user option file */
  233.     sprintf( msgrcname, "%s/%s", homedir, msgrcfn);
  234.     if( (fpmsgrc = fopen(msgrcname,"r")) != NULL ) {
  235.         xomsgrc( fpmsgrc );
  236.         fclose( fpmsgrc );
  237.     }
  238.     restrt = 0;
  239.  
  240.     if( argc > 1)
  241.         strcpy( filename, argv[1] );
  242.     if( argc > 2)
  243.         setmbox( argv[2] );
  244.         
  245.     tt_init();        /* get tty modes */
  246.     setjmp( savej );
  247.     signal (SIGINT, onint);
  248.  
  249.     /*
  250.      * Initial loading of messages
  251.      */
  252.     if( !(restrt++))  {
  253.         status.ms_nmsgs = 0;
  254.         status.ms_curmsg = 0;
  255.         status.ms_markno = 0;
  256.         setup( SETREAD );
  257.     }
  258.  
  259.     if( nottty || argc == 0 || argv[0][0] == 'r' )
  260.         verbose = OFF;
  261.     tt_raw();        /* SET tty modes */
  262.  
  263.     setjmp( savej);
  264.     autoconfirm = FALSE;
  265.     for(;;)  {
  266.         if( outmem == FALSE )
  267.             newmessage();    /* anything arrived recently? */
  268.         printf( "<- ");
  269.         fflush( stdout);
  270.         unset();        /* turn off M_PROCESS_IT bit */
  271.         ascending = TRUE;
  272.         linecount = 0;
  273.  
  274. ignore:        nxtchar = ttychar();
  275.         nxtchar = uptolow( nxtchar);
  276.  
  277.         /* *** KEEP cmdlst[] UP TO DATE WITH LIST OF COMMANDS *** */
  278.         /* It can be found down by the HELP function */
  279.         switch( nxtchar)  {
  280.  
  281.         case 000:    /* null, see also 'X' 'M' */
  282.             if( verbose )
  283.                 printf( "mark set\r\n" );
  284.             status.ms_markno = status.ms_curmsg;
  285.             break;
  286.  
  287.         case 023:    /* ctl/s */
  288.         case 021:    /* ctl/q */
  289.             goto ignore;
  290.  
  291.         case 'a': 
  292.             if( verbose)
  293.                 printf( "answer message: ");
  294.             gitr();
  295.             if( wmsgflag == ON )
  296.                 makedrft();
  297.             ansiter();
  298.             break;
  299.  
  300.         case 002:        /* ^B */
  301.         case 'b': 
  302.             if( verbose)
  303.                 printf( "backup -- previous was:\r\n");
  304.             else
  305.                 suckup();
  306.             if( status.ms_curmsg <= 1)
  307.                 error( "no prior message\r\n");
  308.             msgno = --status.ms_curmsg;
  309.             mptr = msgp[status.ms_curmsg - 1];
  310.             if( mptr->flags & M_DELETED)
  311.                 printf( "# %d deleted\r\n", msgno);
  312.             else
  313.                 prmsg();
  314.             break;
  315.  
  316.         case 'c': 
  317.             if( verbose)
  318.                 printf( "current ");
  319.             printf( "message is %d of %d in %s.  Mark at message %d\r\n",
  320.                 status.ms_curmsg, status.ms_nmsgs, filename, status.ms_markno);
  321.             break;
  322.  
  323.         case 'd': 
  324.             if( verbose)
  325.                 printf( "delete ");
  326.             if( readonly == TRUE ) {
  327.                 printf("in READONLY mode - ignored\r\n");
  328.                 break;
  329.             }
  330.             gitr();
  331.             doiter( delmsg);
  332.             if ((j = cntproc()) > 1)
  333.                 printf("%d messages deleted\r\n", j);
  334.             break;
  335.  
  336.         case 'e': 
  337.             if( readonly == TRUE ) {
  338.                 if( verbose )
  339.                     printf( " quit - READONLY mode" );
  340.             }
  341.             else
  342.                 if( verbose)  {
  343.                     printf( "exit and update %s", filename);
  344.                     if( ismainbox )
  345.                         printf( " into %s", defmbox);
  346.                     printf( "\r\n"  );
  347.                 }
  348.             if( !confirm((char *)0,DOLF))
  349.                 break;
  350.             if( readonly == TRUE ) {
  351.                 tt_norm();
  352.                 closeup(0);
  353.             }
  354.  
  355.             newmessage();        /* Check for new ones */
  356.  
  357.             /* If the message hasn't fully arrived, inform the
  358.              * user, and return to command level.  We depend
  359.              * on a subsequent newmessage() to pick up the
  360.              * new message.
  361.              */
  362.             if(
  363.                 stat( filename, &statb2) >= 0 &&
  364.                 statb2.st_mtime != status.ms_time
  365.             )  {
  366.                 printf( "'%s' updated since last read ...\r\n",
  367.                     filename);
  368.                 break;
  369.             }
  370.             fflush( stdout);
  371.  
  372.             /*
  373.              * Special processing for main mailbox
  374.              */
  375.             if( ismainbox )  {
  376.                 autoconfirm = FALSE;
  377.                 strcpy( outfile, defmbox);
  378.  
  379.                 /* tag all undeleted messages for action */
  380.                 unset();
  381.                 settype( 'u');
  382.  
  383.                 /*
  384.                  * un-tag all KEEP messages
  385.                  * Also, don't flush out messages which
  386.                  * have just arrived and haven't been
  387.                  * seen by the user yet.
  388.                  */
  389.                 for( mp = &msgp[0]; mp < &msgp[status.ms_nmsgs]; mp++ )  {
  390.                     if( (*mp)->flags & (M_KEEP) )
  391.                         (*mp)->flags &= ~M_PROCESS_IT;
  392.                     if( (*mp)->flags & (M_NEW) ) {
  393.  
  394.                         (*mp)->flags &= ~M_PROCESS_IT;
  395.                     }
  396.                 }
  397.  
  398.                 /* MOVE all un-deleted, un-kept messages
  399.                  * into the Mbox file.
  400.                  */
  401.  
  402.                 if( (j = cntproc()) > 0) {
  403.                     printf("Moving %d undeleted messages to %s\r\n", j, outfile);
  404.                     cpyiter( movmsg, DOIT,( int( *)()) 0);
  405.                     /* Delete all msgs moved into Mbox */
  406.                     doiter( delmsg);
  407.                 }
  408.             }
  409.  
  410.             /*
  411.              * Overwrite mailbox.  Note that if some of the
  412.              * messages were marked as "keep", they will be
  413.              * retained in the mailbox, all by themselves.
  414.              */
  415.             overwrit();
  416.             binbuild();
  417.  
  418.             tt_norm();
  419.             closeup(0);
  420.  
  421.         case 'f': 
  422.             if( verbose)
  423.                 printf( "forward ");
  424.             gitr();
  425.             fwditer();
  426.             break;
  427.  
  428.         case 'g': 
  429.             if( verbose)
  430.                 printf( "go to message number: ");
  431.             gitr();
  432.             doiter( gomsg);
  433.             break;
  434.  
  435.         case 'h': 
  436.             if( verbose)
  437.                 printf( "headers ");
  438.             gitr();
  439.             doiter( prhdr);
  440.             break;
  441.  
  442.         case 'j': 
  443.             xeq( 'j' );
  444.             break;
  445.  
  446.         case 'k':
  447.             if( verbose )
  448.                 printf("keep ");
  449.             if( readonly == TRUE ) {
  450.                 printf("in READONLY mode - ignored\r\n");
  451.                 break;
  452.             }
  453.             gitr();
  454.             doiter( keepmsg );
  455.             break;
  456.  
  457.         case 'l': 
  458.             if( verbose)
  459.                 printf( "list ");
  460.             gitr();
  461.             getfn( "to file/pipe: ", outfile, "/dev/tty");
  462.             if( cntproc() > 1)  {
  463.                 printf( "Separate messages");
  464.                 lstsep = confirm((char *)0,DOLF);
  465.             }  else
  466.                 lstsep = FALSE;
  467.  
  468.             if ( prettylist) {
  469.                 lstmore = TRUE;
  470.                 cpyiter( hdrfile, DOIT, dolstmsg);
  471.             }
  472.             else {
  473.                 lstmore = FALSE;
  474.                 cpyiter( lstmsg, DOIT,( int( *)()) 0);
  475.             }
  476.             break;
  477.  
  478.         case 'm': 
  479.             if( verbose)
  480.                 printf( "move ");
  481.             gitr();
  482.             getfn( "to file/pipe: ", outfile, defoutfile);
  483.             cpyiter( movmsg, DOIT,( int( *)()) 0);
  484.             break;
  485.  
  486.         case '/':     /* Delete current, Next */
  487.             if( verbose)
  488.                 printf( "delete current\r\n");
  489.             if( readonly == TRUE ) {
  490.                 printf("in READONLY mode - ignored\r\n");
  491.                 break;
  492.             }
  493.             if( status.ms_nmsgs == 0)  {
  494.                 printf( "'%s' is empty\r\n", filename);
  495.                 error( "" );
  496.             }
  497.             unset();
  498.             if( status.ms_curmsg == 0)  {
  499.                 if( status.ms_nmsgs != 0)
  500.                     status.ms_curmsg = 1;
  501.                 else
  502.                     if( status.ms_curmsg > status.ms_nmsgs)
  503.                         error( "no current message\r\n");
  504.             }
  505.             setrange( status.ms_curmsg, status.ms_curmsg);
  506.             doiter( delmsg);
  507.             /* Fall Through to case 'n' */
  508.  
  509.         case 016:    /* ^N */
  510.         case 'n': 
  511.             if( verbose)
  512.                 printf( "next message is:\r\n");
  513.             else
  514.                 suckup();
  515.             if( status.ms_curmsg >= status.ms_nmsgs)
  516.                 error( "no next message\r\n");
  517.             mptr = msgp[status.ms_curmsg];
  518.             msgno = ++status.ms_curmsg;
  519.             if( mptr->flags & M_DELETED)
  520.                 printf( "message %d deleted\r\n", msgno);
  521.             else
  522.                 prmsg();
  523.             break;
  524.  
  525.         case 'o': 
  526.             if( verbose)
  527.                 printf( "overwrite old file %s", filename);
  528.             if( readonly == TRUE ) {
  529.                 printf(" in READONLY mode - ignored\r\n");
  530.                 break;
  531.             }
  532.             if( confirm((char *)0,DOLF))  {
  533.                 overwrit();
  534.                 outmem = FALSE;
  535.             }
  536.             break;
  537.  
  538.         case 'p': 
  539.             if( verbose)
  540.                 printf( "put ");
  541.             gitr();
  542.             getfn( "to file/pipe: ", outfile, defoutfile);
  543.             cpyiter( putmsg, DOIT,( int( *)()) 0);
  544.             break;
  545.  
  546.         case 004:        /* ^D -- EOF */
  547.         case 'q': 
  548.             if( verbose)
  549.                 printf( "quit");
  550.             if( confirm((char *)0,DOLF))  {
  551.                 tt_norm();
  552.                 binbuild();
  553.                 closeup(0);
  554.             }
  555.             break;
  556.  
  557.         case 'r': 
  558.             /* Update the old binary box */
  559.             binbuild();
  560.  
  561.             if( verbose)
  562.                 printf( "read ");
  563.             else
  564.                 suckup();
  565.             getfn( "new file: ", filename, maininbox);
  566.             setup( SETREAD);
  567.             break;
  568.  
  569.         case 's': 
  570.             if( verbose)
  571.                 printf( "send ");
  572.             if( confirm((char *)0,DOLF)) {
  573.                 if( wmsgflag == ON && status.ms_curmsg != 0 ) {
  574.                     setrange( status.ms_curmsg,status.ms_curmsg );
  575.                     makedrft();
  576.                 }
  577.                 xeq( 'S');
  578.             }
  579.             break;
  580.  
  581.         case 't': 
  582.             if( verbose)
  583.                 printf( "type ");
  584.             gitr();
  585.             doiter( prmsg);
  586.             break;
  587.  
  588.         case 'u': 
  589.             if( verbose)
  590.                 printf( "undelete ");
  591.             if( readonly == TRUE ) {
  592.                 printf("in READONLY mode - ignored\r\n");
  593.                 break;
  594.             }
  595.             gitr();
  596.             doiter( undelmsg);
  597.             if ((j = cntproc()) > 1)
  598.                 printf("%d messages undeleted\r\n", j);
  599.             break;
  600.  
  601.         case 'x':
  602.             if( verbose)
  603.                 printf( "Xtra command: ");
  604.             fflush( stdout);
  605.  
  606.             while( isspace(nxtchar = ttychar()));
  607.             nxtchar = uptolow( nxtchar);
  608.  
  609.             switch(nxtchar) {
  610.  
  611.             case 'b':
  612.                 if( verbose)
  613.                     printf( "binary file write");
  614.                  if( readonly == TRUE ) {
  615.                     printf(" in READONLY mode - ignored\r\n");
  616.                     break;
  617.                 }
  618.                 if( confirm((char *)0,DOLF))
  619.                     binbuild();
  620.                 break;
  621.  
  622.             case 'c':
  623.                 if( filoutflag == OFF ) {
  624.                     if( verbose )
  625.                         printf( "Ctrl char filter on\r\n" );
  626.                     filoutflag = ON;
  627.                 }
  628.                 else {
  629.                     if( verbose )
  630.                         printf( "Ctrl char filter off\r\n" );
  631.                     filoutflag = OFF;
  632.                 }
  633.                 break;
  634.  
  635.             case 'd':
  636.                 printf("debug\r\n");
  637.                 if (status.ms_nmsgs == 0)
  638.                     printf ("No message read in...");
  639.                 else {
  640.                     if( status.ms_curmsg < 1 )
  641.                         status.ms_curmsg = 1;
  642.                     mptr=msgp[status.ms_curmsg-1];
  643.                     printf("\r\nstart=%ld, len=%ld\r\n",mptr->start, mptr->len);
  644.                     printf("Date: %s\r",ctime(&mptr->date));
  645.                     printf("Datestr: %.*s\r\n", SIZEDATE, mptr->datestr);
  646.                     printf("From: %.*s\r\n", SIZEFROM, mptr->from);
  647.                     printf("To: %.*s\r\n", SIZETO, mptr->to);
  648.                     printf("Subj: %.*s\r\n", SIZESUBJ, mptr->subject);
  649.                 }
  650.                 break;
  651.  
  652.             case '\004':
  653.             case 'e': 
  654.                 if( verbose )
  655.                     printf( "exit without saves " );
  656.  
  657.                 if( confirm((char *)0,DOLF)) {
  658.                     tt_norm();
  659.                     closeup(0);
  660.                 }
  661.                 break;
  662.  
  663.             case 'l': 
  664.                 if( verbose)
  665.                     printf( "list body ");
  666.                 gitr();
  667.                 getfn( "to file/pipe: ", outfile, "/dev/tty");
  668.                 if( cntproc() > 1)  {
  669.                     printf( "Separate messages");
  670.                     lstsep = confirm((char *)0,DOLF);
  671.                 }  else
  672.                     lstsep = FALSE;
  673.                 lstmore = FALSE;
  674.                 cpyiter( lstbdy, DOIT, ( int( *)()) 0);
  675.                 break;
  676.  
  677.             case 000:    /* see also null in main switch */
  678.             case 'm':
  679.                 if( verbose )
  680.                     printf( "mark set\r\n" );
  681.                 status.ms_markno = status.ms_curmsg;
  682.                 break;
  683.  
  684.             case 'n':
  685.                 if( prettylist == OFF ) {
  686.                     if( verbose )
  687.                         printf( "Numbered list on\r\n" );
  688.                     prettylist = ON;
  689.                 }
  690.                 else {
  691.                     if( verbose )
  692.                         printf( "Numbered list off\r\n" );
  693.                     prettylist = OFF;
  694.                 }
  695.                 break;
  696.  
  697.             case 'o':
  698.                 if (!verbose)
  699.                     suckup();
  700.                 getfn( "output mbox file: ", defmbox, (char *)0);
  701.                 setmbox(defmbox);
  702.                 break;
  703.  
  704.             case 'p':
  705.                 if( paging == OFF ) {
  706.                     if( verbose )
  707.                         printf( "Paging on\r\n" );
  708.                     paging = ON;
  709.                 }
  710.                 else {
  711.                     if( verbose )
  712.                         printf( "Paging off\r\n" );
  713.                     paging = OFF;
  714.                 }
  715.                 break;
  716.  
  717.             case 'r':
  718.                 if( verbose )
  719.                     printf("re-order key: ");
  720.                 sortbox();
  721.                 break;
  722.  
  723.             case 's':
  724.                 if( keystrip == OFF ) {
  725.                     if( verbose )
  726.                         printf( "Strip on\r\n" );
  727.                     keystrip = ON;
  728.                 }
  729.                 else {
  730.                     if( verbose )
  731.                         printf( "Strip off\r\n" );
  732.                     keystrip = OFF;
  733.                 }
  734.                 break;
  735.  
  736.             case 'v':
  737.                 if( verbose)  {       
  738.                     printf("Verbose off -- Short form typeout\r\n");
  739.                     tt_norm();
  740.                     verbose = 0;
  741.                     goto dont_suck;
  742.                 }  else  {       
  743.                     suckup();
  744.                     if( nottty) error("input not tty\r\n");
  745.                     printf("Verbose on -- Long form typeout\r\n");
  746.                     verbose++;
  747.                     tt_raw();
  748.                 }
  749.                 break;
  750.  
  751.             case 'x':
  752.                 xostat();
  753.                 break;
  754.  
  755.             case '?': 
  756.                 help(xtcmdlst);
  757.                 break;
  758.  
  759.             default: 
  760.                 printf( " ...not a command( type ? for help )\r\n");
  761.  
  762.             }
  763.             break;
  764.  
  765.         case 'y':
  766.             if( verbose )
  767.                 printf("Resend ");
  768.             gitr();
  769.             doiter(prhdr);
  770.             printf("To: ");
  771.             strcpy(outfile,resendprog);
  772.             if( (outfile[strlen(resendprog)]=rdnxtfld()) == '\n' )
  773.                 error("Cancelled\r\n");
  774.             else {
  775.                 gather( &outfile[strlen(resendprog)], 200 );
  776.                 if( verbose )
  777.                     printf("Sending ");
  778.                 doiter( resendmsg );
  779.                 if( verbose )
  780.                     printf(" Done\r\n");
  781.             }
  782.             break;
  783.  
  784.         case 'z':
  785.             if( verbose)
  786.                 printf( "z = two window mode.  Answer message: ");
  787.             gitr();
  788.             edansiter();
  789.             break;
  790.  
  791.         case '\n': 
  792.             if( verbose )
  793.                 printf( "\r\n" );
  794.             break;
  795.  
  796.         case '!': 
  797.             if( verbose )
  798.                 printf("!");
  799.             if( (key[0] = rdnxtfld()) == '\n' ) {
  800.                 if (verbose) printf("\r\n");
  801.                 xeq( 's' );
  802.             }
  803.             else {
  804.                 gather( key, 79 );
  805.                 xeq( '!' );
  806.             }
  807.             printf("\r\n");
  808.             break;
  809.  
  810.         case '?': 
  811.             help(cmdlst);
  812.             break;
  813.  
  814.         case ':': 
  815.             if (verbose) printf( ": ");
  816.             xeq( 'd');
  817.             break;
  818.  
  819.         case ';': 
  820.             if (verbose) printf( "; ");
  821.             do
  822.                 nxtchar = echochar();
  823.             while( nxtchar != '\n' && nxtchar != '\004' );
  824.             break;
  825.  
  826.         case ',':
  827.             if (verbose) printf(",\r\n");
  828.             setrange(
  829.                 (status.ms_curmsg <= 5) ? 1 : status.ms_curmsg - 5,
  830.                 (status.ms_curmsg + 5 > status.ms_nmsgs) ? status.ms_nmsgs : status.ms_curmsg+5
  831.             );
  832.             doiter( prhdr );
  833.             break;
  834.  
  835.         case '@':
  836.             if (verbose)
  837.                 printf( "@ = Undigestify " );
  838.             gitr();
  839.             printf( "Undigestifying " );
  840.             doiter( undigestify );
  841.             printf( "\r\n" );
  842.             break;
  843.  
  844.         case '$':
  845.             /* Drop down to the last message */
  846.             if (verbose)
  847.                 printf("$ = Last message:\r\n");
  848.             status.ms_curmsg = status.ms_nmsgs;
  849.             setrange( status.ms_nmsgs, status.ms_nmsgs);
  850.             doiter( prhdr );
  851.             break;
  852.  
  853.         case '\177':       /* DEL end */
  854.             printf( "use control-D or 'q' to exit\r\n");
  855.             break;
  856.  
  857.         default: 
  858.             printf( " ...not a command( type ? for help)\r\n");
  859.         }
  860.         if( !(verbose || nxtchar == '\n'))
  861.             suckup();
  862. dont_suck:;
  863.     }
  864. }
  865.